package com.lzc.springcloud.user.application;

import com.lzc.springcloud.user.application.representation.User;
import com.lzc.springcloud.user.domain.identity.SysRoleEntity;
import com.lzc.springcloud.user.domain.identity.SysUserEntity;
import com.lzc.springcloud.user.infrastructure.persistence.SysUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;

import java.util.*;

/**
 * Created by Administrator on 2017/6/7.
 */
@Service
@Transactional
public class UserDetailsServiceImpl implements ReactiveUserDetailsService {

    @Autowired
    private SysUserRepository userRepository;

    @Override
    public Mono<UserDetails> findByUsername(String username) {

        SysUserEntity user = userRepository.findByUsername(username);
        Set<String> roles = new HashSet<>();
        if (user == null) {
            return Mono.error(new UsernameNotFoundException("用户名不存在"));
        }
        for (SysRoleEntity sysRoleEntity : user.roleEntities()) {
            roles.add(sysRoleEntity.getRoleName());
        }
        List<GrantedAuthority> grantedAuthorities = this.buildGrantedAuthorities(roles);
        User users = this.buildUserForAuthentication(user, grantedAuthorities);
        return Mono.justOrEmpty((UserDetails)users).switchIfEmpty(Mono.error(new UsernameNotFoundException("用户名不存在")));
    }

    private List<GrantedAuthority> buildGrantedAuthorities(Set<String> roles) {
        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        roles.forEach(role->grantedAuthorities.add(new SimpleGrantedAuthority(role)));
        return grantedAuthorities;
    }

    private List<GrantedAuthority> buildGrantedAuthorities(String role) {
        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        grantedAuthorities.add(new SimpleGrantedAuthority(role));
        return grantedAuthorities;
    }

    private User buildUserForAuthentication(SysUserEntity user, List<GrantedAuthority> authorities){
        String username = user.username();
        String password = user.password();
        return new User(user.userId() + "", username, password, authorities);
    }
}
